﻿using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Virgee.Common.Serializers;
using Virgee.Common.Interfaces;
using System.Web.Http.SelfHost;
using System.Web.Http;
using Microsoft.Practices.Unity;
using Virgee.Common.Services.Exceptions;
using Virgee.Common.Services.Tests.Models;
using Virgee.Common.Services.Tests.Support;
using Virgee.Common.Services.Clients;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Virgee.Common.Services.Tests
{
    /// <summary>
    /// Summary description for HttpServiceClientTests
    /// </summary>
    [TestClass]
    public class HttpServiceClientTests
    {
        private static HttpSelfHostServer _server;
        private static readonly HttpSelfHostConfiguration _config;
        private const string ServiceAddress = "http://localhost:23456/";

        [ThreadStatic]
        private static IUnityContainer _unityContainer;

        static HttpServiceClientTests()
        {
            // Setup classes used to support tests.
            _unityContainer = new UnityContainer();
            _config = new HttpSelfHostConfiguration(ServiceAddress);
            _config.Routes.MapHttpRoute("DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            _config.DependencyResolver = new TestIoCContainer(_unityContainer);
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }


        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            // Start up the test service.
            _server = new HttpSelfHostServer(_config);
            _server.OpenAsync();
        }
        
        
        [ClassCleanup()]
        public static void MyClassCleanup()
        {
            // Shut down the test service
            _server.CloseAsync().Wait();
            _server.Dispose();
        }


        #region Construction Tests

        [TestMethod]
        [TestCategory("Construction")]
        public void Constructor_Requires_Serializer_Test()
        {
            // Arrange
            bool constructionSucceded = false;
            string failedParamterName = null;
            ISerializer serializer = null;

            // Act
            try
            {
                HttpServiceClient httpSvcClient = new HttpServiceClient(serializer);
                constructionSucceded = true;
            }
            catch (ArgumentNullException e)
            {
                constructionSucceded = false;
                failedParamterName = e.ParamName;
            }

            // Assert
            Assert.AreEqual(false, constructionSucceded);
            Assert.AreEqual("serializer", failedParamterName);
        }

        #endregion // Construction Tests

        #region GET Tests
        [TestMethod]
        [TestCategory("GET")]
        public void Synchronous_Get_Uri()
        {
            // Arrange
            TestModel resource = null;
            Uri uri = new Uri(ServiceAddress + "api/TestApi/1");
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(uri);

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Synchronous_Get_UriString_ResourceId()
        {
            // Arrange
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Synchronous_Get_UriString_Query()
        {
            // Arrange
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            IEnumerable<KeyValuePair<string, string>> query = new[] { new KeyValuePair<string, string>("id", "1") };

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", query);

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Asynchronous_Get_Uri()
        {
            // Arrange
            TestModel resource = null;
            Uri uri = new Uri(ServiceAddress + "api/TestApi/1");
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.GetAsync<TestModel>(uri).Result;

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Asynchronous_Get_Uri_CancellationToken()
        {
            // Arrange
            Uri uri = new Uri(ServiceAddress + "api/TestApi/-1"); // id -1 will take a long time to return.
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            CancellationTokenSource cts = new CancellationTokenSource();
            bool callSucceeded = false;
            
            // Act
            Task<TestModel> task = httpSvcClient.GetAsync<TestModel>(uri, cts.Token);

            try
            {
                // let the request start....
                Thread.Sleep(100); 
                cts.Cancel();                 
                
                task.Wait();

                // should never reach this point.
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }
            // Assert
            Assert.IsFalse(callSucceeded);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Asynchronous_Get_UriString_ResourceId()
        {
            // Arrange
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.GetAsync<TestModel>(ServiceAddress + "api/TestApi/", 1).Result;

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Asynchronous_Get_UriString_Query()
        {
            // Arrange
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            IEnumerable<KeyValuePair<string, string>> query = new[] { new KeyValuePair<string, string>("id", "1") };

            // Act
            resource = httpSvcClient.GetAsync<TestModel>(ServiceAddress + "api/TestApi/", query).Result;

            // Assert
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual("Original Test Model", resource.Name);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Synchronous_Get_Invalid_UriString_ResourceId_Fails()
        {
            // Arrange
            TestModel resource = null;
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/invalidcontroller/", 1);
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }

            // Assert
            Assert.IsFalse(callSucceeded);
        }

        [TestMethod]
        [TestCategory("GET")]
        public void Synchronous_Get_UriString_Invalid_ResourceId_Fails()
        {
            // Arrange
            TestModel resource = null;
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", -23);
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }

            // Assert
            Assert.IsFalse(callSucceeded);
        }

        #endregion // GET Tests

        #region POST Tests

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_UriString_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            httpSvcClient.Post(ServiceAddress + "api/TestApi", resource);
            var models = httpSvcClient.Get<List<TestModel>>(new Uri(ServiceAddress + "api/TestApi"));

            // Assert
            Assert.IsNotNull(models);
            Assert.AreEqual(1, models.Count(m => m.Name == nameValue));
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_Uri_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            httpSvcClient.Post(new Uri(ServiceAddress + "api/TestApi"), resource);
            var models = httpSvcClient.Get<List<TestModel>>(new Uri(ServiceAddress + "api/TestApi"));

            // Assert
            Assert.IsNotNull(models);
            Assert.AreEqual(1, models.Count(m => m.Name == nameValue));
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Asynchronous_Post_UriString_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            httpSvcClient.PostAsync(ServiceAddress + "api/TestApi", resource).Wait();
            var models = httpSvcClient.Get<List<TestModel>>(new Uri(ServiceAddress + "api/TestApi"));

            // Assert
            Assert.IsNotNull(models);
            Assert.AreEqual(1, models.Count(m => m.Name == nameValue));
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Asynchronous_Post_Uri_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            httpSvcClient.PostAsync(new Uri(ServiceAddress + "api/TestApi"), resource).Wait();
            var models = httpSvcClient.Get<List<TestModel>>(new Uri(ServiceAddress + "api/TestApi"));

            // Assert
            Assert.IsNotNull(models);
            Assert.AreEqual(1, models.Count(m => m.Name == nameValue));
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_UriString_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Post<TestModel>(ServiceAddress + "api/TestApi", resource);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_Uri_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Post<TestModel>(new Uri(ServiceAddress + "api/TestApi"), resource);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Aynchronous_Post_UriString_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.PostAsync<TestModel>(ServiceAddress + "api/TestApi", resource).Result;

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Asynchronous_Post_Uri_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.PostAsync<TestModel>(new Uri(ServiceAddress + "api/TestApi"), resource).Result;

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_FormData_Files()
        {
            // Arrange
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            List<KeyValuePair<string, string>> formData = new List<KeyValuePair<string, string>>();
            formData.Add(new KeyValuePair<string,string>("key", "value1"));
            formData.Add(new KeyValuePair<string,string>("key", "value1"));
            List<string> files = new List<string>();
            
            string tempFile = Path.GetTempFileName();
            File.WriteAllText(tempFile, "tempcontent");
            files.Add(tempFile);

            // Act
            try
            {
                httpSvcClient.Post(new Uri(ServiceAddress + "api/TestApi2"), formData, files); ;
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }
            finally
            {
                if(File.Exists(tempFile)) 
                {
                    try 
                    {
                        File.Delete(tempFile);
                    }
                    catch
                    {
                    }
                }
            }

            // Assert
            Assert.IsTrue(callSucceeded);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Asynchronous_Post_FormData_Files()
        {
            // Arrange
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            List<KeyValuePair<string, string>> formData = new List<KeyValuePair<string, string>>();
            formData.Add(new KeyValuePair<string, string>("key", "value1"));
            formData.Add(new KeyValuePair<string, string>("key", "value1"));
            List<string> files = new List<string>();

            string tempFile = Path.GetTempFileName();
            File.WriteAllText(tempFile, "tempcontent");
            files.Add(tempFile);

            // Act
            try
            {
                httpSvcClient.PostAsync(new Uri(ServiceAddress + "api/TestApi2"), formData, files).Wait();
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }
            finally
            {
                if (File.Exists(tempFile))
                {
                    try
                    {
                        File.Delete(tempFile);
                    }
                    catch
                    {
                    }
                }
            }

            // Assert
            Assert.IsTrue(callSucceeded);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_Invalid_UriString_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            bool callSucceeded = false;
            TestModel resource = new TestModel { Name = nameValue };
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                httpSvcClient.Post(ServiceAddress + "api/invalidcontroller", resource);
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }

            // Assert
            Assert.IsFalse(callSucceeded);
        }

        [TestMethod]
        [TestCategory("POST")]
        public void Synchronous_Post_UriString_Null_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            bool callSucceeded = false;
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                httpSvcClient.Post(ServiceAddress + "api/TestApi", resource);
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }

            // Assert
            Assert.IsFalse(callSucceeded);
        }
        #endregion POST Tests

        #region PUT Tests
        [TestMethod]
        [TestCategory("PUT")]
        public void Synchronous_Put_UriString_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            httpSvcClient.Put(ServiceAddress + "api/TestApi/", 1, resource);
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Synchronous_Put_Uri_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            httpSvcClient.Put(new Uri(ServiceAddress + "api/TestApi/1"), resource);
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Asynchronous_Put_UriString_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            httpSvcClient.PutAsync(ServiceAddress + "api/TestApi/", 1, resource).Wait();
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Asynchronous_Put_Uri_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            httpSvcClient.PutAsync(new Uri(ServiceAddress + "api/TestApi/1"), resource).Wait();
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Synchronous_Put_UriString_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            resource = httpSvcClient.Put<TestModel>(ServiceAddress + "api/TestApi/", 1, resource);
            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Synchronous_Put_Uri_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            resource = httpSvcClient.Put<TestModel>(new Uri(ServiceAddress + "api/TestApi/1"), resource);

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Asynchronous_Put_UriString_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            resource = httpSvcClient.PutAsync<TestModel>(ServiceAddress + "api/TestApi/", 1, resource).Result;
            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Asynchronous_Put_Uri_Object_ReturnsModel()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", 1);
            resource.Name = nameValue;
            resource = httpSvcClient.PutAsync<TestModel>(new Uri(ServiceAddress + "api/TestApi/1"), resource).Result;

            // Assert
            Assert.IsNotNull(resource);
            Assert.AreEqual(1, resource.Id);
            Assert.AreEqual(nameValue, resource.Name);
        }

        [TestMethod]
        [TestCategory("PUT")]
        public void Synchronous_Put_UriString_Null_Object()
        {
            // Arrange
            string nameValue = Guid.NewGuid().ToString();
            TestModel resource = null;
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                httpSvcClient.Put(ServiceAddress + "api/TestApi/", 1, resource);
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }           

            // Assert
            Assert.IsFalse(callSucceeded);
        }
        #endregion

        #region DELETE Tests
        [TestMethod]
        [TestCategory("DELETE")]
        public void Synchronous_Delete_Uri()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            Uri uri = new Uri(ServiceAddress + "api/TestApi/" + resource.Id);


            // Act
            httpSvcClient.Delete(uri);
            try
            {
                resource = httpSvcClient.Get<TestModel>(uri);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Synchronous_Delete_UriString_ResourceId()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
                        
            // Act
            httpSvcClient.Delete(ServiceAddress + "api/TestApi/", resource.Id);
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", resource.Id);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Asynchronous_Delete_UriString_ResourceId()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            httpSvcClient.DeleteAsync(ServiceAddress + "api/TestApi/", resource.Id).Wait();
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", resource.Id);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Asynchronous_Delete_Uri()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            Uri uri = new Uri(ServiceAddress + "api/TestApi/" + resource.Id);

            // Act
            httpSvcClient.DeleteAsync(uri).Wait();
            try
            {
                resource = httpSvcClient.Get<TestModel>(uri);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;

            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Synchronous_Delete_Uri_ReturnsModel()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            int resourceId = resource.Id;
            Uri uri = new Uri(ServiceAddress + "api/TestApi/" + resourceId);

            // Act
            resource = httpSvcClient.Delete<TestModel>(uri);
            try
            {
                resource = httpSvcClient.Get<TestModel>(uri);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
            Assert.IsNotNull(resource);
            Assert.AreEqual(resourceId, resource.Id);
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Synchronous_Delete_UriString_ResourceId_ReturnsModel()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            int resourceId = resource.Id;            

            // Act
            resource = httpSvcClient.Delete<TestModel>(ServiceAddress + "api/TestApi/", resourceId);
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", resourceId);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
            Assert.IsNotNull(resource);
            Assert.AreEqual(resourceId, resource.Id);
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Asynchronous_Delete_Uri_ReturnsModel()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            int resourceId = resource.Id;
            Uri uri = new Uri(ServiceAddress + "api/TestApi/" + resourceId);

            // Act
            resource = httpSvcClient.DeleteAsync<TestModel>(uri).Result;
            try
            {
                resource = httpSvcClient.Get<TestModel>(uri);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
            Assert.IsNotNull(resource);
            Assert.AreEqual(resourceId, resource.Id);
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Asynchronous_Delete_UriString_ResourceId_ReturnsModel()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callFailed = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());
            int resourceId = resource.Id;

            // Act
            resource = httpSvcClient.DeleteAsync<TestModel>(ServiceAddress + "api/TestApi/", resourceId).Result;
            try
            {
                resource = httpSvcClient.Get<TestModel>(ServiceAddress + "api/TestApi/", resourceId);
                callFailed = false;
            }
            catch (AggregateException)
            {
                callFailed = true;
            }

            Assert.IsTrue(callFailed, "Either DELETE or GET is broken, GET returned a DELETED object.");
            Assert.IsNotNull(resource);
            Assert.AreEqual(resourceId, resource.Id);
        }

        [TestMethod]
        [TestCategory("DELETE")]
        public void Synchronous_Delete_Invalid_Uri()
        {
            // Arrange
            TestModel resource = EnsureModelExist();
            bool callSucceeded = false;
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            // Act
            try
            {
                httpSvcClient.Delete(new Uri(ServiceAddress + "api/invalidcontroller/" + resource.Id));
                callSucceeded = true;
            }
            catch
            {
                callSucceeded = false;
            }


            Assert.IsFalse(callSucceeded);
        }        
        #endregion // DELETE Tests

        #region Utilities
        private static TestModel EnsureModelExist()
        {
            HttpServiceClient httpSvcClient = new HttpServiceClient(new JsonSerializer());

            TestModel resource = new TestModel { Name = "Original Test Model" };
            var models = httpSvcClient.Get<List<TestModel>>(new Uri(ServiceAddress + "api/TestApi"));
            if (!models.Any())
            {
                resource = httpSvcClient.Post<TestModel>(ServiceAddress + "api/TestApi", resource);
            }
            else
            {
                resource = models.First();
            }

            return resource;

        }
        #endregion // Utilities

    }
}

